#!/usr/bin/env bash

set -o nounset
set -o errexit
set -o pipefail

USAGE=$(cat << 'END_OF_LINE'
Configure a developement environment for this repository.

It does the following:
  - Verifies pyenv and pyenv-virtualenv are installed.
  - Creates a Python virtual environment.
  - Configures the activation of the virtual enviroment for the repo directory.
  - Installs the requirements needed for development.
  - Installs git pre-commit hooks.
  - Configures git upstream remote "lineage" repositories.

Usage:
  setup-env [options] [virt_env_name]
  setup-env (-h | --help)

Options:
  -f --force          Delete virtual enviroment if it already exists.
  -h --help           Show this message.
  -i --install-hooks  Install hook environments for all environments in the
                      pre-commit config file.

END_OF_LINE
)

# Flag to force deletion and creation of virtual environment
FORCE=0

# Positional parameters
PARAMS=""

# Parse command line arguments
while (( "$#" )); do
  case "$1" in
    -f|--force)
      FORCE=1
      shift
      ;;
    -h|--help)
      echo "${USAGE}"
      exit 0
      ;;
    -i|--install-hooks)
      INSTALL_HOOKS=1
      shift
      ;;
    -*) # unsupported flags
      echo "Error: Unsupported flag $1" >&2
      exit 1
      ;;
    *) # preserve positional arguments
      PARAMS="$PARAMS $1"
      shift
      ;;
  esac
done

# set positional arguments in their proper place
eval set -- "$PARAMS"

# Check to see if pyenv is installed
if [ -z "$(command -v pyenv)" ] || [ -z "$(command -v pyenv-virtualenv)" ]; then
  echo "pyenv and pyenv-virtualenv are required."
  if [[ "$OSTYPE" == "darwin"* ]]; then
    cat << 'END_OF_LINE'

  On the Mac, we recommend installing brew, https://brew.sh/.  Then installation
  is as simple as `brew install pyenv pyenv-virtualenv` and adding this to your
  profile:

  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"

END_OF_LINE

  fi
  cat << 'END_OF_LINE'
  For Linux, Windows Subsystem for Linux (WSL), or on the Mac (if you don't want
  to use "brew") you can use https://github.com/pyenv/pyenv-installer to install
  the necessary tools. Before running this ensure that you have installed the
  prerequisites for your platform according to the pyenv wiki page,
  https://github.com/pyenv/pyenv/wiki/common-build-problems.

  On WSL you should treat your platform as whatever Linux distribution you've
  chosen to install.

  Once you have installed "pyenv" you will need to add the following lines to
  your ".bashrc":

  export PATH="$PATH:$HOME/.pyenv/bin"
  eval "$(pyenv init -)"
  eval "$(pyenv virtualenv-init -)"
END_OF_LINE
  exit 1
fi

set +o nounset
# Determine the virtual environment name
if [ "$1" ]; then
  # Use the user-provided environment name
  env_name=$1
else
  # Set the environment name to the last part of the working directory.
  env_name=${PWD##*/}
fi
set -o nounset

# Remove any lingering local configuration.
if [ $FORCE -ne 0 ]; then
  rm -f .python-version
  pyenv virtualenv-delete --force "${env_name}" || true
elif [[ -f .python-version ]]; then
  cat << 'END_OF_LINE'
  An existing .python-version file was found.  Either remove this file yourself
  or re-run with --force option to have it deleted along with the associated
  virtual environment.

  rm .python-version

END_OF_LINE
  exit 1
fi

# Create a new virtual environment for this project
if ! pyenv virtualenv "${env_name}"; then
  cat << END_OF_LINE
  An existing virtual environment named $env_name was found.  Either delete this
  environment yourself or re-run with --force option to have it deleted.

  pyenv virtualenv-delete ${env_name}

END_OF_LINE
  exit 1
fi

# Set the local application-specific Python version(s) by writing the
# version name to a file named `.python-version'.
pyenv local "${env_name}"

# Upgrade pip and friends
python3 -m pip install --upgrade pip setuptools wheel

# Find a requirements file (if possible) and install
for req_file in "requirements-dev.txt" "requirements-test.txt" "requirements.txt"; do
  if [[ -f $req_file ]]; then
    pip install --requirement $req_file
    break
  fi
done

# Install git pre-commit hooks now or later.
pre-commit install ${INSTALL_HOOKS:+"--install-hooks"}

# Setup git remotes from lineage configuration
# This could fail if the remotes are already setup, but that is ok.
set +o errexit

eval "$(python3 << 'END_OF_LINE'
from pathlib import Path
import yaml
import sys

LINEAGE_CONFIG = Path(".github/lineage.yml")

if not LINEAGE_CONFIG.exists():
    print("No lineage configuration found.", file=sys.stderr)
    sys.exit(0)

with LINEAGE_CONFIG.open("r") as f:
    lineage = yaml.safe_load(stream=f)

if lineage["version"] == "1":
    for parent_name, v in lineage["lineage"].items():
        remote_url = v["remote-url"]
        print(f"git remote add {parent_name} {remote_url};")
        print(f"git remote set-url --push {parent_name} no_push;")
else:
    print(f'Unsupported lineage version: {lineage["version"]}', file=sys.stderr)
END_OF_LINE
)"

# Qapla
echo "Success!"
